#define ZCORE_SOURCE
#include "Port.hpp"
#include "StringPrintf.hpp"

namespace zzz {
void StringAppendV(string &dst, const char *format, va_list ap)
{
  char data[512];
  va_list oldap;
  va_copy(oldap, ap);
  int result = vsnprintf(data, sizeof(data), format, oldap);
  va_end(oldap);

  if (result >= 0 && result < sizeof(data)) {
    dst.append(data, result);
    return;
  }

  int length = sizeof(data);
  while(true) {
    if (result < 0) {
      length *= 2;
    } else {
      length = result + 1;
    }
    char *moredata = new char[length];

    va_copy(oldap, ap);
    result = vsnprintf(moredata, length, format, oldap);
    va_end(oldap);

    if (result > 0 && result < length) {
      dst.append(moredata, result);
      delete[] moredata;
      return;
    }
    delete[] moredata;
  }
}

string StringPrintf(const char *format, ...)
{
  va_list ap;
  va_start(ap, format);
  string result;
  StringAppendV(result, format, ap);
  va_end(ap);
  return result;
}

const string &SStringPrintf(string &dst, const char *format, ...)
{
  va_list ap;
  va_start(ap, format);
  dst.clear();
  StringAppendV(dst, format, ap);
  va_end(ap);
  return dst;
}

void StringAppendF(string &dst, const char *format, ...)
{
  va_list ap;
  va_start(ap, format);
  StringAppendV(dst, format ,ap);
  va_end(ap);
}
}  // namespace zzz
